home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmiSoft / Hard / Drivr / 3c589.lha / 3c589 / Source / unit.c < prev   
C/C++ Source or Header  |  2003-02-08  |  46KB  |  2,178 lines

  1. /*
  2.  
  3. File: unit.c
  4. Author: Neil Cafferkey
  5. Copyright (C) 2001-2003 Neil Cafferkey
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  20. MA 02111-1307, USA.
  21.  
  22. */
  23.  
  24.  
  25. #include <exec/memory.h>
  26. #include <exec/execbase.h>
  27. #include <exec/errors.h>
  28.  
  29. #include <proto/exec.h>
  30. #include <proto/alib.h>
  31. #include <proto/cardres.h>
  32. #include <proto/utility.h>
  33. #include <proto/pccard.h>
  34. #include <proto/timer.h>
  35.  
  36. #include "device.h"
  37. #include "etherlink3.h"
  38.  
  39. #include "unit_protos.h"
  40. #include "request_protos.h"
  41.  
  42.  
  43. #define TASK_PRIORITY 0
  44. #define STACK_SIZE 4096
  45. #define MAX_TUPLE_SIZE 0xff
  46. #define TUPLE_BUFFER_SIZE (MAX_TUPLE_SIZE+8)
  47. #define INT_MASK\
  48.    (EL3INTF_RXCOMPLETE|EL3INTF_TXAVAIL|EL3INTF_TXCOMPLETE|EL3INTF_FAILURE)
  49.  
  50.  
  51. IMPORT struct ExecBase *AbsExecBase;
  52.  
  53. static BOOL InitialiseCard(struct DevUnit *unit,struct DevBase *base);
  54. static VOID InitialiseAdapter(struct DevUnit *unit,struct DevBase *base);
  55. static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
  56.    ULONG lower_bound_left,UWORD lower_bound_right,ULONG upper_bound_left,
  57.    UWORD upper_bound_right,struct DevBase *base);
  58. static VOID CardRemovedInt(struct DevUnit *unit REG("a1"));
  59. static VOID CardInsertedInt(struct DevUnit *unit REG("a1"));
  60. static UBYTE CardStatusInt(UBYTE mask REG("d0"),
  61.    struct DevUnit *unit REG("a1"));
  62. static VOID RxInt(struct DevUnit *unit REG("a1"));
  63. static VOID CopyPacket(struct DevUnit *unit,struct IOSana2Req *request,
  64.    UWORD packet_size,UWORD packet_type,BOOL all_read,struct DevBase *base);
  65. static BOOL AddressFilter(struct DevUnit *unit,UBYTE *address,
  66.    struct DevBase *base);
  67. static VOID TxInt(struct DevUnit *unit REG("a1"));
  68. static VOID TxError(struct DevUnit *unit,struct DevBase *base);
  69. static VOID ReportEvents(struct DevUnit *unit,ULONG events,
  70.    struct DevBase *base);
  71. static VOID UnitTask();
  72. static UWORD ReadEEPROM(volatile UBYTE *io_base,UWORD index);
  73. static UWORD LEWordIn(volatile UBYTE *address);
  74.  
  75.  
  76.  
  77. /****i* 3c589.device/GetUnit ***********************************************
  78. *
  79. *   NAME
  80. *    GetUnit -- Get a unit by number.
  81. *
  82. *   SYNOPSIS
  83. *    unit = GetUnit(unit_num)
  84. *
  85. *    struct DevUnit *GetUnit(ULONG);
  86. *
  87. *   FUNCTION
  88. *
  89. *   INPUTS
  90. *
  91. *   RESULT
  92. *
  93. *   EXAMPLE
  94. *
  95. *   NOTES
  96. *
  97. *   BUGS
  98. *
  99. *   SEE ALSO
  100. *
  101. ****************************************************************************
  102. *
  103. */
  104.  
  105. struct DevUnit *GetUnit(ULONG unit_num,struct DevBase *base)
  106. {
  107.    struct DevUnit *unit;
  108.  
  109.    unit=FindUnit(unit_num,base);
  110.  
  111.    if(unit==NULL)
  112.    {
  113.       unit=CreateUnit(unit_num,base);
  114.       if(unit!=NULL)
  115.          AddTail((APTR)&base->units,(APTR)unit);
  116.    }
  117.  
  118.    return unit;
  119. }
  120.  
  121.  
  122.  
  123. /****i* 3c589.device/FindUnit **********************************************
  124. *
  125. *   NAME
  126. *    FindUnit -- Find a unit by number.
  127. *
  128. *   SYNOPSIS
  129. *    unit = FindUnit(unit_num)
  130. *
  131. *    struct DevUnit *FindUnit(ULONG);
  132. *
  133. *   FUNCTION
  134. *
  135. *   INPUTS
  136. *
  137. *   RESULT
  138. *
  139. *   EXAMPLE
  140. *
  141. *   NOTES
  142. *
  143. *   BUGS
  144. *
  145. *   SEE ALSO
  146. *
  147. ****************************************************************************
  148. *
  149. */
  150.  
  151. struct DevUnit *FindUnit(ULONG unit_num,struct DevBase *base)
  152. {
  153.    struct DevUnit *unit,*tail;
  154.    BOOL found;
  155.  
  156.    unit=(APTR)base->units.mlh_Head;
  157.    tail=(APTR)&base->units.mlh_Tail;
  158.    found=FALSE;
  159.  
  160.    while((unit!=tail)&&!found)
  161.    {
  162.       if(unit->unit_num==unit_num)
  163.          found=TRUE;
  164.       else
  165.          unit=(APTR)unit->node.mln_Succ;
  166.    }
  167.  
  168.    if(!found)
  169.       unit=NULL;
  170.  
  171.    return unit;
  172. }
  173.  
  174.  
  175.  
  176. /****i* 3c589.device/CreateUnit ********************************************
  177. *
  178. *   NAME
  179. *    CreateUnit -- Create a unit.
  180. *
  181. *   SYNOPSIS
  182. *    unit = CreateUnit(unit_num)
  183. *
  184. *    struct DevUnit *CreateUnit(ULONG);
  185. *
  186. *   FUNCTION
  187. *    Creates a new unit.
  188. *
  189. *   INPUTS
  190. *
  191. *   RESULT
  192. *
  193. *   EXAMPLE
  194. *
  195. *   NOTES
  196. *
  197. *   BUGS
  198. *
  199. *   SEE ALSO
  200. *
  201. ****************************************************************************
  202. *
  203. */
  204.  
  205. struct DevUnit *CreateUnit(ULONG unit_num,struct DevBase *base)
  206. {
  207.    BOOL success=TRUE;
  208.    struct DevUnit *unit;
  209.    struct Task *task;
  210.    struct MsgPort *port;
  211.    UBYTE i;
  212.    struct CardHandle *card_handle;
  213.    APTR stack;
  214.    struct Interrupt *card_removed_int,*card_inserted_int,*card_status_int;
  215.  
  216.    unit=AllocMem(sizeof(struct DevUnit),MEMF_CLEAR);
  217.    if(unit==NULL)
  218.       success=FALSE;
  219.  
  220.    if(success)
  221.    {
  222.       unit->unit_num=unit_num;
  223.       unit->device=base;
  224.  
  225.       InitSemaphore(&unit->access_lock);
  226.  
  227.       /* Set up packet filter command */
  228.  
  229.       unit->rx_filter_cmd=EL3CMD_SETRXFILTER|EL3CMD_SETRXFILTERF_BCAST
  230.          |EL3CMD_SETRXFILTERF_UCAST;
  231.  
  232.       /* Create the message ports for queuing requests */
  233.  
  234.       for(i=0;i<REQUEST_QUEUE_COUNT;i++)
  235.       {
  236.          unit->request_ports[i]=port=AllocMem(sizeof(struct MsgPort),
  237.             MEMF_PUBLIC|MEMF_CLEAR);
  238.          if(port==NULL)
  239.             success=FALSE;
  240.  
  241.          if(success)
  242.          {
  243.             NewList(&port->mp_MsgList);
  244.             port->mp_Flags=PA_IGNORE;
  245.             port->mp_SigTask=&unit->tx_int;
  246.          }
  247.       }
  248.  
  249.       card_handle=unit->card_handle=
  250.          AllocMem(sizeof(struct CardHandle),MEMF_PUBLIC|MEMF_CLEAR);
  251.       unit->tuple_buffer=
  252.          AllocVec(TUPLE_BUFFER_SIZE,MEMF_ANY);
  253.       unit->rx_buffer=AllocVec((MAX_PACKET_SIZE+3)&~3,MEMF_PUBLIC);
  254.       unit->tx_buffer=AllocVec(MAX_PACKET_SIZE,MEMF_PUBLIC);
  255.       if((card_handle==NULL)||(unit->tuple_buffer==NULL)||
  256.          (unit->rx_buffer==NULL)||(unit->tx_buffer==NULL))
  257.          success=FALSE;
  258.    }
  259.  
  260.    if(success)
  261.    {
  262.       NewList((APTR)&unit->openers);
  263.       NewList((APTR)&unit->type_trackers);
  264.       NewList((APTR)&unit->multicast_ranges);
  265.  
  266.       /* Initialise transmit and receive interrupts */
  267.  
  268.       unit->rx_int.is_Node.ln_Name=(TEXT *)device_name;
  269.       unit->rx_int.is_Node.ln_Pri=16;
  270.       unit->rx_int.is_Code=RxInt;
  271.       unit->rx_int.is_Data=unit;
  272.  
  273.       unit->tx_int.is_Node.ln_Name=(TEXT *)device_name;
  274.       unit->tx_int.is_Code=TxInt;
  275.       unit->tx_int.is_Data=unit;
  276.  
  277.       unit->request_ports[WRITE_QUEUE]->mp_Flags=PA_SOFTINT;
  278.    }
  279.  
  280.    if(success)
  281.    {
  282.       /* Set up card handle */
  283.  
  284.       card_handle->cah_CardNode.ln_Pri=HANDLE_PRIORITY;
  285.       card_handle->cah_CardNode.ln_Name=(APTR)device_name;
  286.       card_handle->cah_CardFlags=CARDF_IFAVAILABLE;
  287.  
  288.       card_handle->cah_CardRemoved=card_removed_int=
  289.          AllocVec(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR);
  290.  
  291.       card_handle->cah_CardInserted=card_inserted_int=
  292.          AllocVec(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR);
  293.  
  294.       card_handle->cah_CardStatus=card_status_int=
  295.          AllocVec(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR);
  296.  
  297.       if((card_removed_int==NULL)
  298.          ||(card_inserted_int==NULL)
  299.          ||(card_status_int==NULL))
  300.          success=FALSE;
  301.    }
  302.  
  303.    if(success)
  304.    {
  305.       /* Try to gain access to card */
  306.  
  307.       card_removed_int->is_Code=CardRemovedInt;
  308.       card_removed_int->is_Data=unit;
  309.       card_inserted_int->is_Code=CardInsertedInt;
  310.       card_inserted_int->is_Data=unit;
  311.       card_status_int->is_Code=(APTR)CardStatusInt;
  312.       card_status_int->is_Data=unit;
  313.  
  314.       if(OwnCard(card_handle)!=0)
  315.          success=FALSE;
  316.    }
  317.  
  318.    if(success)
  319.    {
  320.       unit->flags|=UNITF_HAVECARD;
  321.       if(!InitialiseCard(unit,base))
  322.          success=FALSE;
  323.  
  324.       /* Create a new task */
  325.  
  326.       unit->task=task=AllocMem(sizeof(struct Task),MEMF_PUBLIC|MEMF_CLEAR);
  327.       if(task==NULL)
  328.          success=FALSE;
  329.    }
  330.  
  331.    if(success)
  332.    {
  333.       stack=AllocMem(STACK_SIZE,MEMF_PUBLIC);
  334.       if(stack==NULL)
  335.          success=FALSE;
  336.    }
  337.  
  338.    if(success)
  339.    {
  340.       /* Initialise and start task */
  341.  
  342.       task->tc_Node.ln_Type=NT_TASK;
  343.       task->tc_Node.ln_Pri=TASK_PRIORITY;
  344.       task->tc_Node.ln_Name=(APTR)device_name;
  345.       task->tc_SPUpper=stack+STACK_SIZE;
  346.       task->tc_SPLower=stack;
  347.       task->tc_SPReg=stack+STACK_SIZE;
  348.  
  349.       if(AddTask(task,UnitTask,NULL)==NULL)
  350.          success=FALSE;
  351.    }
  352.  
  353.    /* Send the unit to the new task */
  354.  
  355.    if(success)
  356.       task->tc_UserData=unit;
  357.  
  358.    if(!success)
  359.    {
  360.       DeleteUnit(unit,base);
  361.       unit=NULL;
  362.    }
  363.  
  364.    return unit;
  365. }
  366.  
  367.  
  368.  
  369. /****i* 3c589.device/DeleteUnit ********************************************
  370. *
  371. *   NAME
  372. *    DeleteUnit -- Delete a unit.
  373. *
  374. *   SYNOPSIS
  375. *    DeleteUnit(unit)
  376. *
  377. *    VOID DeleteUnit(struct DevUnit *);
  378. *
  379. *   FUNCTION
  380. *    Deletes a unit.
  381. *
  382. *   INPUTS
  383. *    unit - Device unit (can be NULL).
  384. *
  385. *   RESULT
  386. *    None.
  387. *
  388. *   EXAMPLE
  389. *
  390. *   NOTES
  391. *
  392. *   BUGS
  393. *
  394. *   SEE ALSO
  395. *
  396. ****************************************************************************
  397. *
  398. */
  399.  
  400. VOID DeleteUnit(struct DevUnit *unit,struct DevBase *base)
  401. {
  402.    UBYTE i;
  403.    struct CardHandle *card_handle;
  404.    struct Task *task;
  405.  
  406.    if(unit!=NULL)
  407.    {
  408.       task=unit->task;
  409.       if(task!=NULL)
  410.       {
  411.          if(task->tc_SPLower!=NULL)
  412.          {
  413.             RemTask(task);
  414.             FreeMem(task->tc_SPLower,STACK_SIZE);
  415.          }
  416.          FreeMem(task,sizeof(struct Task));
  417.       }
  418.  
  419.       for(i=0;i<REQUEST_QUEUE_COUNT;i++)
  420.       {
  421.          if(unit->request_ports[i]!=NULL)
  422.             FreeMem(unit->request_ports[i],sizeof(struct MsgPort));
  423.       }
  424.  
  425.       FreeVec(unit->tuple_buffer);
  426.  
  427.       card_handle=unit->card_handle;
  428.       if(card_handle!=NULL)
  429.       {
  430.          if((unit->flags&UNITF_HAVECARD)!=0)
  431.          {
  432.             if((unit->flags&UNITF_HAVEADAPTER)!=0)
  433.                GoOffline(unit,base);
  434.  
  435.             CardMiscControl(card_handle,0);
  436.             CardResetCard(card_handle);
  437.             ReleaseCard(card_handle,CARDF_REMOVEHANDLE);
  438.          }
  439.  
  440.          FreeVec(card_handle->cah_CardStatus);
  441.          FreeVec(card_handle->cah_CardInserted);
  442.          FreeVec(card_handle->cah_CardRemoved);
  443.  
  444.          FreeMem(card_handle,sizeof(struct CardHandle));
  445.       }
  446.  
  447.       FreeVec(unit->tx_buffer);
  448.       FreeVec(unit->rx_buffer);
  449.  
  450.       FreeMem(unit,sizeof(struct DevUnit));
  451.    }
  452.  
  453.    return;
  454. }
  455.  
  456.  
  457.  
  458. /****i* 3c589.device/InitialiseCard ****************************************
  459. *
  460. *   NAME
  461. *    InitialiseCard -- .
  462. *
  463. *   SYNOPSIS
  464. *    success = InitialiseCard(unit)
  465. *
  466. *    BOOL InitialiseCard(struct DevUnit *);
  467. *
  468. *   FUNCTION
  469. *
  470. *   INPUTS
  471. *    unit
  472. *
  473. *   RESULT
  474. *    success
  475. *
  476. *   EXAMPLE
  477. *
  478. *   NOTES
  479. *
  480. *   BUGS
  481. *
  482. *   SEE ALSO
  483. *
  484. ****************************************************************************
  485. *
  486. */
  487.  
  488. static BOOL InitialiseCard(struct DevUnit *unit,struct DevBase *base)
  489. {
  490.    BOOL success=TRUE;
  491.    struct CardMemoryMap *card_map;
  492.    struct CardHandle *card_handle;
  493.    UBYTE config_value,i,window_count,*tuple_buffer;
  494.    const struct TagItem *tuple_tags=NULL;
  495.    ULONG *io_bases,*io_lengths,io_base=0,config_base_offset;
  496.    UWORD maker,product;
  497.  
  498.    /* Wake up card */
  499.  
  500.    card_handle=unit->card_handle;
  501.    CardMiscControl(card_handle,CARD_ENABLEF_DIGAUDIO|CARD_DISABLEF_WP);
  502.  
  503.    /* Get card's make and model */
  504.  
  505.    tuple_buffer=unit->tuple_buffer;
  506.    if(CopyTuple(card_handle,tuple_buffer,PCCARD_TPL_MANFID,MAX_TUPLE_SIZE))
  507.    {
  508.       tuple_tags=PCCard_GetTupleInfo(tuple_buffer);
  509.       if(tuple_tags!=NULL)
  510.       {
  511.          maker=GetTagData(PCCARD_Maker,0,tuple_tags);
  512.          product=GetTagData(PCCARD_Product,0,tuple_tags);
  513.       }
  514.    }
  515.  
  516.    /* Check this is a card we can use */
  517.  
  518.    if((tuple_tags==NULL)||!((maker==0x101)&&((product==0x35)||
  519.       (product==0x3d)||(product==0x562)||(product==0x589))))
  520.       success=FALSE;
  521.  
  522.    /* Get configuration data */
  523.  
  524.    if(!CopyTuple(card_handle,tuple_buffer,PCCARD_TPL_CONFIG,MAX_TUPLE_SIZE))
  525.       success=FALSE;
  526.  
  527.    if(success)
  528.    {
  529.       tuple_tags=PCCard_GetTupleInfo(tuple_buffer);
  530.       if(tuple_tags==NULL)
  531.          success=FALSE;
  532.    }
  533.  
  534.    if(success)
  535.    {
  536.       config_base_offset=GetTagData(PCCARD_RegisterBase,0,tuple_tags);
  537.  
  538.       PCCard_FreeTupleInfo(tuple_tags);
  539.       tuple_tags=NULL;
  540.  
  541.       /* Get IO base */
  542.  
  543.       if(!CopyTuple(card_handle,tuple_buffer,PCCARD_TPL_CFTABLEENTRY,
  544.          MAX_TUPLE_SIZE))
  545.          success=FALSE;
  546.    }
  547.  
  548.    if(success)
  549.    {
  550.       tuple_tags=PCCard_GetTupleInfo(tuple_buffer);
  551.       if(tuple_tags==NULL)
  552.          success=FALSE;
  553.    }
  554.  
  555.    if(success)
  556.    {
  557.       config_value=GetTagData(PCCARD_ModeNo,0,tuple_tags);
  558.  
  559.       io_bases=(APTR)GetTagData(PCCARD_IOWinBases,NULL,tuple_tags);
  560.       if(io_bases==NULL)
  561.          success=FALSE;
  562.    }
  563.  
  564.    if(success)
  565.    {
  566.       io_lengths=(APTR)GetTagData(PCCARD_IOWinLengths,NULL,tuple_tags);
  567.  
  568.       window_count=GetTagData(PCCARD_IOWinCount,0,tuple_tags);
  569.  
  570.       for(i=0;(i<window_count)&&(io_base==0);i++)
  571.          if(io_lengths[i]==16)
  572.             io_base=io_bases[i];
  573.    }
  574.  
  575.    PCCard_FreeTupleInfo(tuple_tags);
  576.  
  577.    /* Configure card */
  578.  
  579.    if(success)
  580.    {
  581.       card_map=GetCardMap();
  582.       unit->config_base=card_map->cmm_AttributeMemory+config_base_offset;
  583.  
  584.       unit->io_base=card_map->cmm_IOMemory+io_base;
  585.       unit->config_base[PCCARD_REG_COR]=config_value;
  586.       unit->config_base[PCCARD_REG_CCSR]|=PCCARD_REG_CCSRF_AUDIOENABLE;
  587.  
  588.       InitialiseAdapter(unit,base);
  589.       unit->flags|=UNITF_HAVEADAPTER;
  590.    }
  591.  
  592.    return success;
  593. }
  594.  
  595.  
  596.  
  597. /****i* 3c589.device/InitialiseAdapter *************************************
  598. *
  599. *   NAME
  600. *    InitialiseAdapter -- .
  601. *
  602. *   SYNOPSIS
  603. *    InitialiseAdapter(unit)
  604. *
  605. *    VOID InitialiseAdapter(struct DevUnit *);
  606. *
  607. *   FUNCTION
  608. *
  609. *   INPUTS
  610. *    unit
  611. *
  612. *   RESULT
  613. *    None.
  614. *
  615. *   EXAMPLE
  616. *
  617. *   NOTES
  618. *
  619. *   BUGS
  620. *
  621. *   SEE ALSO
  622. *
  623. ****************************************************************************
  624. *
  625. */
  626.  
  627. static VOID InitialiseAdapter(struct DevUnit *unit,struct DevBase *base)
  628. {
  629.    volatile UBYTE *io_base;
  630.    UBYTE *p,i;
  631.    UWORD address_part,config,link,media,new_media,medium,media_status;
  632.  
  633.    /* Select IO addresses and interrupt */
  634.  
  635.    io_base=unit->io_base;
  636.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|0);
  637.    LEWordOut(io_base+EL3REG_RESCONFIG,0x3f00);
  638.  
  639.    /* Get default MAC address */
  640.  
  641.    p=unit->default_address;
  642.  
  643.    for(i=0;i<ADDRESS_SIZE/2;i++)
  644.    {
  645.       address_part=ReadEEPROM(io_base,EL3EEPROM_ALTADDRESS0+i);
  646.       *p++=address_part>>8;
  647.       *p++=address_part&0xff;
  648.    }
  649.  
  650.    /* Get available transceivers */
  651.  
  652.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|0);
  653.    media=LEWordIn(io_base+EL3REG_CONFIG);
  654.  
  655.    /* Get transceivers with an active link */
  656.  
  657.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|4);
  658.    link=0;
  659.    media_status=LEWordIn(io_base+EL3REG_MEDIA);
  660.    if((media_status&EL3REG_MEDIAF_BEAT)!=0)
  661.       link|=EL3REG_CONFIGF_HASTP;
  662.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|0);
  663.  
  664.    new_media=media&link;
  665.    if((new_media)!=0)
  666.       media=new_media;
  667.    else
  668.    {
  669.       /* Get transceiver choice from EEPROM */
  670.  
  671.       config=ReadEEPROM(io_base,EL3EEPROM_ADDRCONFIG)&
  672.          (EL3REG_ADDRCONFIG_XCVRMASK|EL3REG_ADDRCONFIGF_AUTOSELECT);
  673.  
  674.       if(config=EL3REG_ADDRCONFIG_XCVRTP)
  675.          new_media=EL3REG_CONFIGF_HASTP;
  676.       else if(config=EL3REG_ADDRCONFIG_XCVRAUI)
  677.          new_media=EL3REG_CONFIGF_HASAUI;
  678.       else if(config=EL3REG_ADDRCONFIG_XCVRCOAX)
  679.          new_media=EL3REG_CONFIGF_HASCOAX;
  680.       else
  681.          new_media=EL3REG_CONFIGF_HASTP|EL3REG_CONFIGF_HASCOAX|
  682.             EL3REG_CONFIGF_HASAUI;
  683.  
  684.       new_media&=media;
  685.       if(new_media!=0)
  686.          media=new_media;
  687.    }
  688.  
  689.    /* Prioritised choice from remaining transceivers */
  690.  
  691.    if((media&EL3REG_CONFIGF_HASTP)!=0)
  692.       medium=EL3REG_ADDRCONFIG_XCVRTP;
  693.    else if((media&EL3REG_CONFIGF_HASCOAX)!=0)
  694.       medium=EL3REG_ADDRCONFIG_XCVRCOAX;
  695.    else
  696.       medium=EL3REG_ADDRCONFIG_XCVRAUI;
  697.    unit->transceiver=medium;
  698.  
  699.    return;
  700. }
  701.  
  702.  
  703.  
  704. /****i* 3c589.device/ConfigureAdapter **************************************
  705. *
  706. *   NAME
  707. *    ConfigureAdapter -- .
  708. *
  709. *   SYNOPSIS
  710. *    ConfigureAdapter(unit)
  711. *
  712. *    VOID ConfigureAdapter(struct DevUnit *);
  713. *
  714. *   FUNCTION
  715. *
  716. *   INPUTS
  717. *    unit
  718. *
  719. *   RESULT
  720. *    None.
  721. *
  722. *   EXAMPLE
  723. *
  724. *   NOTES
  725. *
  726. *   BUGS
  727. *
  728. *   SEE ALSO
  729. *
  730. ****************************************************************************
  731. *
  732. */
  733.  
  734. VOID ConfigureAdapter(struct DevUnit *unit,struct DevBase *base)
  735. {
  736.    volatile UBYTE *io_base;
  737.    UBYTE i;
  738.  
  739.    /* Set MAC address */
  740.  
  741.    io_base=unit->io_base;
  742.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|2);
  743.  
  744.    for(i=0;i<ADDRESS_SIZE;i++)
  745.       ByteOut(io_base+EL3REG_ADDRESS0+i,unit->address[i]);
  746.  
  747.    /* Decide on promiscuous mode */
  748.  
  749.    if((unit->flags&UNITF_PROM)!=0)
  750.       unit->rx_filter_cmd|=EL3CMD_SETRXFILTERF_PROM;
  751.  
  752.    /* Select chosen transceiver */
  753.  
  754.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|0);
  755.    LEWordOut(io_base+EL3REG_ADDRCONFIG,unit->transceiver);
  756.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|1);
  757.  
  758.    /* Go online */
  759.  
  760.    GoOnline(unit,base);
  761.  
  762.    /* Return */
  763.  
  764.    return;
  765. }
  766.  
  767.  
  768.  
  769. /****i* 3c589.device/GoOnline **********************************************
  770. *
  771. *   NAME
  772. *    GoOnline -- .
  773. *
  774. *   SYNOPSIS
  775. *    GoOnline(unit)
  776. *
  777. *    VOID GoOnline(struct DevUnit *);
  778. *
  779. *   FUNCTION
  780. *
  781. *   INPUTS
  782. *    unit
  783. *
  784. *   RESULT
  785. *    None.
  786. *
  787. *   EXAMPLE
  788. *
  789. *   NOTES
  790. *
  791. *   BUGS
  792. *
  793. *   SEE ALSO
  794. *
  795. ****************************************************************************
  796. *
  797. */
  798.  
  799. VOID GoOnline(struct DevUnit *unit,struct DevBase *base)
  800. {
  801.    volatile UBYTE *io_base;
  802.    UWORD transceiver;
  803.  
  804.    /* Choose interrupts */
  805.  
  806.    unit->flags|=UNITF_ONLINE;
  807.    io_base=unit->io_base;
  808.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SETINTMASK|INT_MASK);
  809.    LEWordOut(io_base+EL3REG_COMMAND,(EL3CMD_SETZEROMASK)|0xff);
  810.  
  811.    /* Enable the transceiver */
  812.  
  813.    transceiver=unit->transceiver;
  814.  
  815.    if(transceiver==EL3REG_ADDRCONFIG_XCVRTP)
  816.    {
  817.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|4);
  818.       LEWordOut(io_base+EL3REG_MEDIA,
  819.          EL3REG_MEDIAF_BEATENABLE|EL3REG_MEDIAF_JABBERENABLE);
  820.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|1);
  821.    }
  822.    else if(transceiver==EL3REG_ADDRCONFIG_XCVRCOAX)
  823.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_STARTCOAX|0);
  824.  
  825.    LEWordOut(io_base+EL3REG_COMMAND,unit->rx_filter_cmd);
  826.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_RXENABLE);
  827.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_TXENABLE);
  828.  
  829.    /* Record start time and report Online event */
  830.  
  831.    GetSysTime(&unit->stats.LastStart);
  832.    ReportEvents(unit,S2EVENT_ONLINE,base);
  833.  
  834.    return;
  835. }
  836.  
  837.  
  838.  
  839. /****i* 3c589.device/GoOffline *********************************************
  840. *
  841. *   NAME
  842. *    GoOffline -- .
  843. *
  844. *   SYNOPSIS
  845. *    GoOffline(unit)
  846. *
  847. *    VOID GoOffline(struct DevUnit *);
  848. *
  849. *   FUNCTION
  850. *
  851. *   INPUTS
  852. *    unit
  853. *
  854. *   RESULT
  855. *    None.
  856. *
  857. *   EXAMPLE
  858. *
  859. *   NOTES
  860. *
  861. *   BUGS
  862. *
  863. *   SEE ALSO
  864. *
  865. ****************************************************************************
  866. *
  867. */
  868.  
  869. VOID GoOffline(struct DevUnit *unit,struct DevBase *base)
  870. {
  871.    volatile UBYTE *io_base;
  872.  
  873.    io_base=unit->io_base;
  874.    unit->flags&=~UNITF_ONLINE;
  875.  
  876.    if((unit->flags&UNITF_HAVEADAPTER)!=0)
  877.    {
  878.       /* Stop interrupts */
  879.  
  880.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SETINTMASK|0);
  881.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_ACKINT|EL3INTF_ANY);
  882.  
  883.       /* Stop transmission and reception */
  884.  
  885.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_RXDISABLE);
  886.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_TXDISABLE);
  887.  
  888.       /* Turn off TP functions */
  889.  
  890.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|4);
  891.       LEWordOut(io_base+EL3REG_MEDIA,0);
  892.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SELECTWINDOW|1);
  893.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_STOPCOAX|0);
  894.    }
  895.  
  896.    /* Flush pending read and write requests */
  897.  
  898.    FlushUnit(unit,WRITE_QUEUE,S2ERR_OUTOFSERVICE,base);
  899.  
  900.    /* Report Offline event and return */
  901.  
  902.    ReportEvents(unit,S2EVENT_OFFLINE,base);
  903.    return;
  904. }
  905.  
  906.  
  907.  
  908. /****i* 3c589.device/AddMulticastRange *************************************
  909. *
  910. *   NAME
  911. *    AddMulticastRange -- .
  912. *
  913. *   SYNOPSIS
  914. *    success = AddMulticastRange(unit,lower_bound,upper_bound)
  915. *
  916. *    BOOL AddMulticastRange(struct DevUnit *,UBYTE *,UBYTE *);
  917. *
  918. *   FUNCTION
  919. *
  920. *   INPUTS
  921. *
  922. *   RESULT
  923. *
  924. *   EXAMPLE
  925. *
  926. *   NOTES
  927. *
  928. *   BUGS
  929. *
  930. *   SEE ALSO
  931. *
  932. ****************************************************************************
  933. *
  934. */
  935.  
  936. BOOL AddMulticastRange(struct DevUnit *unit,UBYTE *lower_bound,
  937.    UBYTE *upper_bound,struct DevBase *base)
  938. {
  939.    struct AddressRange *range;
  940.    ULONG lower_bound_left,upper_bound_left;
  941.    UWORD lower_bound_right,upper_bound_right;
  942.  
  943.    lower_bound_left=BELong(*((ULONG *)lower_bound));
  944.    lower_bound_right=BEWord(*((UWORD *)(lower_bound+4)));
  945.    upper_bound_left=BELong(*((ULONG *)upper_bound));
  946.    upper_bound_right=BEWord(*((UWORD *)(upper_bound+4)));
  947.  
  948.    range=FindMulticastRange(unit,lower_bound_left,lower_bound_right,
  949.       upper_bound_left,upper_bound_right,base);
  950.  
  951.    if(range!=NULL)
  952.       range->add_count++;
  953.    else
  954.    {
  955.       range=AllocMem(sizeof(struct AddressRange),MEMF_PUBLIC);
  956.       if(range!=NULL)
  957.       {
  958.          range->lower_bound_left=lower_bound_left;
  959.          range->lower_bound_right=lower_bound_right;
  960.          range->upper_bound_left=upper_bound_left;
  961.          range->upper_bound_right=upper_bound_right;
  962.          range->add_count=1;
  963.  
  964.          Disable();
  965.          AddTail((APTR)&unit->multicast_ranges,(APTR)range);
  966.          Enable();
  967.  
  968.          if(unit->range_count++==0)
  969.          {
  970.             unit->rx_filter_cmd|=EL3CMD_SETRXFILTERF_MCAST;
  971.             LEWordOut(unit->io_base+EL3REG_COMMAND,unit->rx_filter_cmd);
  972.          }
  973.       }
  974.    }
  975.  
  976.    return range!=NULL;
  977. }
  978.  
  979.  
  980.  
  981. /****i* 3c589.device/RemMulticastRange *************************************
  982. *
  983. *   NAME
  984. *    RemMulticastRange -- .
  985. *
  986. *   SYNOPSIS
  987. *    found = RemMulticastRange(unit,lower_bound,upper_bound)
  988. *
  989. *    BOOL RemMulticastRange(struct DevUnit *,UBYTE *,UBYTE *);
  990. *
  991. *   FUNCTION
  992. *
  993. *   INPUTS
  994. *
  995. *   RESULT
  996. *
  997. *   EXAMPLE
  998. *
  999. *   NOTES
  1000. *
  1001. *   BUGS
  1002. *
  1003. *   SEE ALSO
  1004. *
  1005. ****************************************************************************
  1006. *
  1007. */
  1008.  
  1009. BOOL RemMulticastRange(struct DevUnit *unit,UBYTE *lower_bound,
  1010.    UBYTE *upper_bound,struct DevBase *base)
  1011. {
  1012.    struct AddressRange *range;
  1013.    ULONG lower_bound_left,upper_bound_left;
  1014.    UWORD lower_bound_right,upper_bound_right;
  1015.  
  1016.    lower_bound_left=BELong(*((ULONG *)lower_bound));
  1017.    lower_bound_right=BEWord(*((UWORD *)(lower_bound+4)));
  1018.    upper_bound_left=BELong(*((ULONG *)upper_bound));
  1019.    upper_bound_right=BEWord(*((UWORD *)(upper_bound+4)));
  1020.  
  1021.    range=FindMulticastRange(unit,lower_bound_left,lower_bound_right,
  1022.       upper_bound_left,upper_bound_right,base);
  1023.  
  1024.    if(range!=NULL)
  1025.    {
  1026.       if(--range->add_count==0)
  1027.       {
  1028.          Disable();
  1029.          Remove((APTR)range);
  1030.          Enable();
  1031.          FreeMem(range,sizeof(struct AddressRange));
  1032.  
  1033.          if(--unit->range_count==0)
  1034.          {
  1035.             unit->rx_filter_cmd&=~EL3CMD_SETRXFILTERF_MCAST;
  1036.             LEWordOut(unit->io_base+EL3REG_COMMAND,unit->rx_filter_cmd);
  1037.          }
  1038.       }
  1039.    }
  1040.  
  1041.    return range!=NULL;
  1042. }
  1043.  
  1044.  
  1045.  
  1046. /****i* 3c589.device/FindMulticastRange *************************************
  1047. *
  1048. *   NAME
  1049. *    FindMulticastRange -- .
  1050. *
  1051. *   SYNOPSIS
  1052. *    range = FindMulticastRange(unit,lower_bound_left,
  1053. *        lower_bound_right,upper_bound_left,upper_bound_right)
  1054. *
  1055. *    struct AddressRange *FindMulticastRange(struct DevUnit *,ULONG,
  1056. *        UWORD,ULONG,UWORD);
  1057. *
  1058. *   FUNCTION
  1059. *
  1060. *   INPUTS
  1061. *
  1062. *   RESULT
  1063. *
  1064. *   EXAMPLE
  1065. *
  1066. *   NOTES
  1067. *
  1068. *   BUGS
  1069. *
  1070. *   SEE ALSO
  1071. *
  1072. ****************************************************************************
  1073. *
  1074. */
  1075.  
  1076. static struct AddressRange *FindMulticastRange(struct DevUnit *unit,
  1077.    ULONG lower_bound_left,UWORD lower_bound_right,ULONG upper_bound_left,
  1078.    UWORD upper_bound_right,struct DevBase *base)
  1079. {
  1080.    struct AddressRange *range,*tail;
  1081.    BOOL found;
  1082.  
  1083.    range=(APTR)unit->multicast_ranges.mlh_Head;
  1084.    tail=(APTR)&unit->multicast_ranges.mlh_Tail;
  1085.    found=FALSE;
  1086.  
  1087.    while((range!=tail)&&!found)
  1088.    {
  1089.       if((lower_bound_left==range->lower_bound_left)&&
  1090.          (lower_bound_right==range->lower_bound_right)&&
  1091.          (upper_bound_left==range->upper_bound_left)&&
  1092.          (upper_bound_right==range->upper_bound_right))
  1093.          found=TRUE;
  1094.       else
  1095.          range=(APTR)range->node.mln_Succ;
  1096.    }
  1097.  
  1098.    if(!found)
  1099.       range=NULL;
  1100.  
  1101.    return range;
  1102. }
  1103.  
  1104.  
  1105.  
  1106. /****i* 3c589.device/FindTypeStats *****************************************
  1107. *
  1108. *   NAME
  1109. *    FindTypeStats -- .
  1110. *
  1111. *   SYNOPSIS
  1112. *    stats = FindTypeStats(unit,list,
  1113. *        packet_type)
  1114. *
  1115. *    struct TypeStats *FindTypeStats(struct DevUnit *,struct MinList *,
  1116. *        ULONG);
  1117. *
  1118. *   FUNCTION
  1119. *
  1120. *   INPUTS
  1121. *
  1122. *   RESULT
  1123. *
  1124. *   EXAMPLE
  1125. *
  1126. *   NOTES
  1127. *
  1128. *   BUGS
  1129. *
  1130. *   SEE ALSO
  1131. *
  1132. ****************************************************************************
  1133. *
  1134. */
  1135.  
  1136. struct TypeStats *FindTypeStats(struct DevUnit *unit,struct MinList *list,
  1137.    ULONG packet_type,struct DevBase *base)
  1138. {
  1139.    struct TypeStats *stats,*tail;
  1140.    BOOL found;
  1141.  
  1142.    stats=(APTR)list->mlh_Head;
  1143.    tail=(APTR)&list->mlh_Tail;
  1144.    found=FALSE;
  1145.  
  1146.    while((stats!=tail)&&!found)
  1147.    {
  1148.       if(stats->packet_type==packet_type)
  1149.          found=TRUE;
  1150.       else
  1151.          stats=(APTR)stats->node.mln_Succ;
  1152.    }
  1153.  
  1154.    if(!found)
  1155.       stats=NULL;
  1156.  
  1157.    return stats;
  1158. }
  1159.  
  1160.  
  1161.  
  1162. /****i* 3c589.device/FlushUnit *********************************************
  1163. *
  1164. *   NAME
  1165. *    FlushUnit -- .
  1166. *
  1167. *   SYNOPSIS
  1168. *    FlushUnit(unit)
  1169. *
  1170. *    VOID FlushUnit(struct DevUnit *);
  1171. *
  1172. *   FUNCTION
  1173. *
  1174. *   INPUTS
  1175. *
  1176. *   RESULT
  1177. *
  1178. *   EXAMPLE
  1179. *
  1180. *   NOTES
  1181. *
  1182. *   BUGS
  1183. *
  1184. *   SEE ALSO
  1185. *
  1186. ****************************************************************************
  1187. *
  1188. */
  1189.  
  1190. VOID FlushUnit(struct DevUnit *unit,UBYTE last_queue,BYTE error,
  1191.    struct DevBase *base)
  1192. {
  1193.    struct IORequest *request;
  1194.    UBYTE i;
  1195.    struct Opener *opener,*tail;
  1196.  
  1197.    /* Abort queued requests */
  1198.  
  1199.    for(i=0;i<=last_queue;i++)
  1200.    {
  1201.       while((request=(APTR)GetMsg(unit->request_ports[i]))!=NULL)
  1202.       {
  1203.          request->io_Error=IOERR_ABORTED;
  1204.          ReplyMsg((APTR)request);
  1205.       }
  1206.    }
  1207.  
  1208. #if 1
  1209.    opener=(APTR)unit->openers.mlh_Head;
  1210.    tail=(APTR)&unit->openers.mlh_Tail;
  1211.  
  1212.    /* Flush every opener's read queue */
  1213.  
  1214.    while(opener!=tail)
  1215.    {
  1216.       while((request=(APTR)GetMsg(&opener->read_port))!=NULL)
  1217.       {
  1218.          request->io_Error=error;
  1219.          ReplyMsg((APTR)request);
  1220.       }
  1221.       opener=(APTR)opener->node.mln_Succ;
  1222.    }
  1223.  
  1224. #else
  1225.    opener=request->ios2_BufferManagement;
  1226.    while((request=(APTR)GetMsg(&opener->read_port))!=NULL)
  1227.    {
  1228.       request->io_Error=IOERR_ABORTED;
  1229.       ReplyMsg((APTR)request);
  1230.    }
  1231. #endif
  1232.  
  1233.    /* Return */
  1234.  
  1235.    return;
  1236. }
  1237.  
  1238.  
  1239.  
  1240. /****i* 3c589.device/CardRemovedInt ****************************************
  1241. *
  1242. *   NAME
  1243. *    CardRemovedInt -- .
  1244. *
  1245. *   SYNOPSIS
  1246. *    CardRemovedInt(unit)
  1247. *
  1248. *    VOID CardRemovedInt(struct DevUnit *);
  1249. *
  1250. *   FUNCTION
  1251. *
  1252. *   INPUTS
  1253. *    unit
  1254. *
  1255. *   RESULT
  1256. *    None.
  1257. *
  1258. *   EXAMPLE
  1259. *
  1260. *   NOTES
  1261. *
  1262. *   BUGS
  1263. *
  1264. *   SEE ALSO
  1265. *
  1266. ****************************************************************************
  1267. *
  1268. */
  1269.  
  1270. static VOID CardRemovedInt(struct DevUnit *unit REG("a1"))
  1271. {
  1272.    struct DevBase *base;
  1273.  
  1274.    /* Record loss of card and get our task to call ReleaseCard() */
  1275.  
  1276.    base=unit->device;
  1277.    unit->flags&=~(UNITF_HAVEADAPTER|UNITF_HAVECARD|UNITF_ONLINE);
  1278.    Signal(unit->task,unit->card_removed_signal);
  1279.  
  1280.    return;
  1281. }
  1282.  
  1283.  
  1284.  
  1285. /****i* 3c589.device/CardInsertedInt ***************************************
  1286. *
  1287. *   NAME
  1288. *    CardInsertedInt -- .
  1289. *
  1290. *   SYNOPSIS
  1291. *    CardInsertedInt(unit)
  1292. *
  1293. *    VOID CardInsertedInt(struct DevUnit *);
  1294. *
  1295. *   FUNCTION
  1296. *
  1297. *   INPUTS
  1298. *    unit
  1299. *
  1300. *   RESULT
  1301. *    None.
  1302. *
  1303. *   EXAMPLE
  1304. *
  1305. *   NOTES
  1306. *
  1307. *   BUGS
  1308. *
  1309. *   SEE ALSO
  1310. *
  1311. ****************************************************************************
  1312. *
  1313. */
  1314.  
  1315. static VOID CardInsertedInt(struct DevUnit *unit REG("a1"))
  1316. {
  1317.    struct DevBase *base;
  1318.  
  1319.    base=unit->device;
  1320.  
  1321.    Signal(unit->task,unit->card_inserted_signal);
  1322.  
  1323.    return;
  1324. }
  1325.  
  1326.  
  1327.  
  1328. /****i* 3c589.device/CardStatusInt *****************************************
  1329. *
  1330. *   NAME
  1331. *    CardStatusInt -- .
  1332. *
  1333. *   SYNOPSIS
  1334. *    mask = CardStatusInt(mask,unit)
  1335. *
  1336. *    UBYTE CardStatusInt(UBYTE mask,struct DevUnit *);
  1337. *
  1338. *   FUNCTION
  1339. *
  1340. *   INPUTS
  1341. *    mask
  1342. *    unit
  1343. *
  1344. *   RESULT
  1345. *    None.
  1346. *
  1347. *   EXAMPLE
  1348. *
  1349. *   NOTES
  1350. *
  1351. *   BUGS
  1352. *
  1353. *   SEE ALSO
  1354. *
  1355. ****************************************************************************
  1356. *
  1357. */
  1358.  
  1359. static UBYTE CardStatusInt(UBYTE mask REG("d0"),
  1360.    struct DevUnit *unit REG("a1"))
  1361. {
  1362.    struct DevBase *base;
  1363.    volatile UBYTE *io_base;
  1364.    UWORD ints;
  1365.  
  1366.    base=unit->device;
  1367.  
  1368.    if((mask&CARD_STATUSF_IRQ)!=0)
  1369.    {
  1370.       io_base=unit->io_base;
  1371.       ints=LEWordIn(io_base+EL3REG_STATUS);
  1372.  
  1373.       if((ints&EL3INTF_ANY)!=0)   /* ??? */
  1374.       {
  1375.          /* Handle interrupts */
  1376.  
  1377.          if((ints&EL3INTF_RXCOMPLETE)!=0)
  1378.          {
  1379.             LEWordOut(io_base+EL3REG_COMMAND,
  1380.                EL3CMD_SETINTMASK|(INT_MASK&~EL3INTF_RXCOMPLETE));
  1381.  
  1382.             Cause(&unit->rx_int);
  1383.          }
  1384.          if((ints&EL3INTF_TXAVAIL)!=0)
  1385.          {
  1386.             LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_ACKINT|
  1387.                EL3INTF_TXAVAIL);
  1388.             Cause(&unit->tx_int);
  1389.          }
  1390.          if((ints&EL3INTF_TXCOMPLETE)!=0)
  1391.             TxError(unit,base);
  1392.          if((ints&EL3INTF_FAILURE)!=0)
  1393.             *((UWORD *)8)=0x9999;
  1394.  
  1395.          /* Acknowledge interrupt request */
  1396.  
  1397.          LEWordOut(io_base+EL3REG_COMMAND,
  1398.             EL3CMD_ACKINT|EL3INTF_ANY);
  1399.       }
  1400.  
  1401.       /* Work around gayle interrupt bug */
  1402.  
  1403.       *((volatile UBYTE *)0xda9000)=(mask^0x2c)|0xc0;
  1404.       mask=0;
  1405.    }
  1406.  
  1407.    return mask;
  1408. }
  1409.  
  1410.  
  1411.  
  1412. /****i* 3c589.device/RxInt *************************************************
  1413. *
  1414. *   NAME
  1415. *    RxInt -- .
  1416. *
  1417. *   SYNOPSIS
  1418. *    RxInt(unit)
  1419. *
  1420. *    VOID RxInt(struct DevUnit *);
  1421. *
  1422. *   FUNCTION
  1423. *
  1424. *   INPUTS
  1425. *    unit - A unit of this device.
  1426. *
  1427. *   RESULT
  1428. *    None.
  1429. *
  1430. *   EXAMPLE
  1431. *
  1432. *   NOTES
  1433. *
  1434. *   BUGS
  1435. *
  1436. *   SEE ALSO
  1437. *
  1438. ****************************************************************************
  1439. *
  1440. */
  1441.  
  1442. static VOID RxInt(struct DevUnit *unit REG("a1"))
  1443. {
  1444.    volatile UBYTE *io_base;
  1445.    UWORD rx_status,packet_size;
  1446.    struct DevBase *base;
  1447.    BOOL is_orphan=TRUE,all_read,accepted;
  1448.    ULONG packet_type,*p,*end;
  1449.    UBYTE *buffer;
  1450.    struct IOSana2Req *request,*request_tail;
  1451.    struct Opener *opener,*opener_tail;
  1452.    struct TypeStats *tracker;
  1453.  
  1454.    base=unit->device;
  1455.    io_base=unit->io_base;
  1456.  
  1457.    while(((rx_status=LEWordIn(io_base+EL3REG_RXSTATUS))
  1458.       &EL3REG_RXSTATUSF_INCOMPLETE)==0)
  1459.    {
  1460.       if((rx_status&EL3REG_RXSTATUSF_ERROR)==0)
  1461.       {
  1462.          /* Read packet header */
  1463.  
  1464.          all_read=FALSE;
  1465.          packet_size=rx_status&EL3REG_RXSTATUS_SIZEMASK;
  1466.          p=(ULONG *)buffer=unit->rx_buffer;
  1467.          end=(ULONG *)(buffer+PACKET_DATA);
  1468.          while(p<end)
  1469.             *p++=LongIn(io_base+EL3REG_DATA0);
  1470.  
  1471.          if(AddressFilter(unit,buffer+PACKET_DEST,base))
  1472.          {
  1473.             packet_type=BEWord(*((UWORD *)(buffer+PACKET_TYPE)));
  1474.  
  1475.             opener=(APTR)unit->openers.mlh_Head;
  1476.             opener_tail=(APTR)&unit->openers.mlh_Tail;
  1477.  
  1478.             /* Offer packet to every opener */
  1479.  
  1480.             while(opener!=opener_tail)
  1481.             {
  1482.                request=(APTR)opener->read_port.mp_MsgList.lh_Head;
  1483.                request_tail=(APTR)&opener->read_port.mp_MsgList.lh_Tail;
  1484.                accepted=FALSE;
  1485.  
  1486.                /* Offer packet to each request until it's accepted */
  1487.  
  1488.                while((request!=request_tail)&&!accepted)
  1489.                {
  1490.                   if(request->ios2_PacketType==packet_type)
  1491.                   {
  1492.                      CopyPacket(unit,request,packet_size,packet_type,
  1493.                         all_read,base);
  1494.                      accepted=TRUE;
  1495.                   }
  1496.                   request=
  1497.                      (APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
  1498.                }
  1499.  
  1500.                if(accepted)
  1501.                {
  1502.                   is_orphan=FALSE;
  1503.                   all_read=TRUE;
  1504.                }
  1505.                opener=(APTR)opener->node.mln_Succ;
  1506.             }
  1507.  
  1508.             /* If packet was unwanted, give it to S2_READORPHAN request */
  1509.  
  1510.             if(is_orphan)
  1511.             {
  1512.                unit->stats.UnknownTypesReceived++;
  1513.                if(!IsMsgPortEmpty(unit->request_ports[ADOPT_QUEUE]))
  1514.                {
  1515.                   CopyPacket(unit,
  1516.                      (APTR)unit->request_ports[ADOPT_QUEUE]->
  1517.                      mp_MsgList.lh_Head,packet_size,packet_type,all_read,
  1518.                      base);
  1519.                   is_orphan=FALSE;
  1520.                   all_read=TRUE;
  1521.                }
  1522.             }
  1523.  
  1524.             /* Update remaining statistics */
  1525.  
  1526.             unit->stats.PacketsReceived++;
  1527.  
  1528.             tracker=
  1529.                FindTypeStats(unit,&unit->type_trackers,packet_type,base);
  1530.             if(tracker!=NULL)
  1531.             {
  1532.                tracker->stats.PacketsReceived++;
  1533.                tracker->stats.BytesReceived+=packet_size;
  1534.             }
  1535.          }
  1536.       }
  1537.       else
  1538.       {
  1539.          unit->stats.BadData++;
  1540.          ReportEvents(unit,S2EVENT_ERROR|S2EVENT_HARDWARE|S2EVENT_RX,base);
  1541.       }
  1542.  
  1543.       /* Discard packet */
  1544.  
  1545.       Disable();
  1546.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_RXDISCARD);
  1547.       while((LEWordIn(io_base+EL3REG_STATUS)&
  1548.          EL3REG_STATUSF_CMDINPROGRESS)!=0);
  1549.       Enable();
  1550.    }
  1551.  
  1552.    /* Return */
  1553.  
  1554.    LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SETINTMASK|INT_MASK);
  1555.    return;
  1556. }
  1557.  
  1558.  
  1559.  
  1560. /****i* 3c589.device/CopyPacket ********************************************
  1561. *
  1562. *   NAME
  1563. *    CopyPacket -- .
  1564. *
  1565. *   SYNOPSIS
  1566. *    CopyPacket(unit,request,packet_size,packet_type,
  1567. *        all_read)
  1568. *
  1569. *    VOID CopyPacket(struct DevUnit *,struct IOSana2Req *,UWORD,UWORD,
  1570. *        BOOL);
  1571. *
  1572. *   FUNCTION
  1573. *
  1574. *   INPUTS
  1575. *
  1576. *   RESULT
  1577. *
  1578. *   EXAMPLE
  1579. *
  1580. *   NOTES
  1581. *
  1582. *   BUGS
  1583. *
  1584. *   SEE ALSO
  1585. *
  1586. ****************************************************************************
  1587. *
  1588. */
  1589.  
  1590. static VOID CopyPacket(struct DevUnit *unit,struct IOSana2Req *request,
  1591.    UWORD packet_size,UWORD packet_type,BOOL all_read,struct DevBase *base)
  1592. {
  1593.    volatile UBYTE *io_base;
  1594.    struct Opener *opener;
  1595.    UBYTE *buffer;
  1596.    BOOL filtered=FALSE;
  1597.    ULONG *p,*end;
  1598.  
  1599.    /* Set packet length */
  1600.  
  1601.    io_base=unit->io_base;
  1602.  
  1603.    /* Set multicast and broadcast flags */
  1604.  
  1605.    buffer=unit->rx_buffer;
  1606.    request->ios2_Req.io_Flags&=~(SANA2IOB_BCAST|SANA2IOB_MCAST);
  1607.    if((*((ULONG *)(buffer+PACKET_DEST))==0xffffffff)&&
  1608.       (*((UWORD *)(buffer+PACKET_DEST+4))==0xffff))
  1609.       request->ios2_Req.io_Flags|=SANA2IOB_BCAST;
  1610.    else if((buffer[PACKET_DEST]&0x1)!=0)
  1611.       request->ios2_Req.io_Flags|=SANA2IOB_MCAST;
  1612.  
  1613.    /* Set source and destination addresses and packet type */
  1614.  
  1615.    CopyMem(buffer+PACKET_SOURCE,request->ios2_SrcAddr,ADDRESS_SIZE);
  1616.    CopyMem(buffer+PACKET_DEST,request->ios2_DstAddr,ADDRESS_SIZE);
  1617.    request->ios2_PacketType=packet_type;
  1618.  
  1619.    /* Read rest of packet */
  1620.  
  1621.    if(!all_read)
  1622.    {
  1623.       p=(ULONG *)(buffer+((PACKET_DATA+3)&~3));
  1624.       end=(ULONG *)(buffer+packet_size);
  1625.       while(p<end)
  1626.          *p++=LongIn(io_base+EL3REG_DATA0);
  1627.    }
  1628.  
  1629.    if((request->ios2_Req.io_Flags&SANA2IOF_RAW)==0)
  1630.    {
  1631.       packet_size-=PACKET_DATA;
  1632.       buffer+=PACKET_DATA;
  1633.    }
  1634. #ifdef USE_HACKS
  1635.    else
  1636.       packet_size+=4;   /* Needed for Shapeshifter & Fusion */
  1637. #endif
  1638.  
  1639.    request->ios2_DataLength=packet_size;
  1640.  
  1641.    /* Filter packet */
  1642.  
  1643.    opener=request->ios2_BufferManagement;
  1644.    if((request->ios2_Req.io_Command==CMD_READ)&&
  1645.       (opener->filter_hook!=NULL))
  1646.       if(!CallHookPkt(opener->filter_hook,request,buffer))
  1647.          filtered=TRUE;
  1648.  
  1649.    if(!filtered)
  1650.    {
  1651.       /* Copy packet into opener's buffer and reply packet */
  1652.  
  1653.       if(!opener->rx_function(request->ios2_Data,buffer,packet_size))
  1654.       {
  1655.          request->ios2_Req.io_Error=S2ERR_NO_RESOURCES;
  1656.          request->ios2_WireError=S2WERR_BUFF_ERROR;
  1657.          ReportEvents(unit,
  1658.             S2EVENT_ERROR|S2EVENT_SOFTWARE|S2EVENT_BUFF|S2EVENT_RX,base);
  1659.       }
  1660.       Remove((APTR)request);
  1661.       ReplyMsg((APTR)request);
  1662.  
  1663.    }
  1664.  
  1665.    return;
  1666. }
  1667.  
  1668.  
  1669.  
  1670. /****i* 3c589.device/AddressFilter *****************************************
  1671. *
  1672. *   NAME
  1673. *    AddressFilter -- .
  1674. *
  1675. *   SYNOPSIS
  1676. *    accept = AddressFilter(unit,address)
  1677. *
  1678. *    BOOL AddressFilter(struct DevUnit *,UBYTE *);
  1679. *
  1680. *   FUNCTION
  1681. *
  1682. *   INPUTS
  1683. *
  1684. *   RESULT
  1685. *
  1686. *   EXAMPLE
  1687. *
  1688. *   NOTES
  1689. *
  1690. *   BUGS
  1691. *
  1692. *   SEE ALSO
  1693. *
  1694. ****************************************************************************
  1695. *
  1696. */
  1697.  
  1698. static BOOL AddressFilter(struct DevUnit *unit,UBYTE *address,
  1699.    struct DevBase *base)
  1700. {
  1701.    struct AddressRange *range,*tail;
  1702.    BOOL accept=TRUE;
  1703.    ULONG address_left;
  1704.    UWORD address_right;
  1705.  
  1706.    /* Check whether address is unicast/broadcast or multicast */
  1707.  
  1708.    address_left=BELong(*((ULONG *)address));
  1709.    address_right=BEWord(*((UWORD *)(address+4)));
  1710.  
  1711.    if(((address_left&0x01000000)!=0)&&
  1712.       !((address_left==0xffffffff)&&(address_right==0xffff)))
  1713.    {
  1714.       /* Check if this multicast address is wanted */
  1715.  
  1716.       range=(APTR)unit->multicast_ranges.mlh_Head;
  1717.       tail=(APTR)&unit->multicast_ranges.mlh_Tail;
  1718.       accept=FALSE;
  1719.  
  1720.       while((range!=tail)&&!accept)
  1721.       {
  1722.          if(((address_left>range->lower_bound_left)||
  1723.             (address_left==range->lower_bound_left)&&
  1724.             (address_right>=range->lower_bound_right))&&
  1725.             ((address_left<range->upper_bound_left)||
  1726.             (address_left==range->upper_bound_left)&&
  1727.             (address_right<=range->upper_bound_right)))
  1728.             accept=TRUE;
  1729.          range=(APTR)range->node.mln_Succ;
  1730.       }
  1731.  
  1732.       if(!accept)
  1733.          unit->special_stats[S2SS_ETHERNET_BADMULTICAST&0xffff]++;
  1734.    }
  1735.  
  1736.    return accept;
  1737. }
  1738.  
  1739.  
  1740.  
  1741. /****i* 3c589.device/TxInt *************************************************
  1742. *
  1743. *   NAME
  1744. *    TxInt -- .
  1745. *
  1746. *   SYNOPSIS
  1747. *    TxInt(unit)
  1748. *
  1749. *    VOID TxInt(struct DevUnit *);
  1750. *
  1751. *   FUNCTION
  1752. *
  1753. *   INPUTS
  1754. *    unit - A unit of this device.
  1755. *
  1756. *   RESULT
  1757. *    None.
  1758. *
  1759. *   EXAMPLE
  1760. *
  1761. *   NOTES
  1762. *
  1763. *   BUGS
  1764. *
  1765. *   SEE ALSO
  1766. *
  1767. ****************************************************************************
  1768. *
  1769. */
  1770.  
  1771. static VOID TxInt(struct DevUnit *unit REG("a1"))
  1772. {
  1773.    volatile UBYTE *io_base;
  1774.    UWORD packet_size,data_size,send_size;
  1775.    struct DevBase *base;
  1776.    struct IOSana2Req *request;
  1777.    BOOL proceed=TRUE;
  1778.    struct Opener *opener;
  1779.    ULONG *buffer,*end,wire_error;
  1780.    ULONG *(*dma_tx_function)(APTR REG("a0"));
  1781.    BYTE error;
  1782.    struct MsgPort *port;
  1783.    struct TypeStats *tracker;
  1784.  
  1785.    base=unit->device;
  1786.    io_base=unit->io_base;
  1787.  
  1788.    port=unit->request_ports[WRITE_QUEUE];
  1789.  
  1790.    while(proceed&&(!IsMsgPortEmpty(port)))
  1791.    {
  1792.       error=0;
  1793.  
  1794.       request=(APTR)port->mp_MsgList.lh_Head;
  1795.       data_size=packet_size=request->ios2_DataLength;
  1796.  
  1797.       if((request->ios2_Req.io_Flags&SANA2IOF_RAW)==0)
  1798.          packet_size+=PACKET_DATA;
  1799.  
  1800.       if(LEWordIn(io_base+EL3REG_TXSPACE)>PREAMBLE_SIZE+packet_size)
  1801.       {
  1802.          /* Write packet preamble */
  1803.  
  1804.          LELongOut(io_base+EL3REG_DATA0,packet_size);
  1805.  
  1806.          /* Write packet header */
  1807.  
  1808.          send_size=(packet_size+3)&(~0x3);
  1809.          if((request->ios2_Req.io_Flags&SANA2IOF_RAW)==0)
  1810.          {
  1811.             LongOut(io_base+EL3REG_DATA0,*((ULONG *)request->ios2_DstAddr));
  1812.             WordOut(io_base+EL3REG_DATA0,
  1813.                *((UWORD *)(request->ios2_DstAddr+4)));
  1814.             WordOut(io_base+EL3REG_DATA0,*((UWORD *)unit->address));
  1815.             LongOut(io_base+EL3REG_DATA0,*((ULONG *)(unit->address+2)));
  1816.             BEWordOut(io_base+EL3REG_DATA0,request->ios2_PacketType);
  1817.             send_size-=PACKET_DATA;
  1818.          }
  1819.  
  1820.          /* Get packet data */
  1821.  
  1822.          opener=(APTR)request->ios2_BufferManagement;
  1823.          dma_tx_function=opener->dma_tx_function;
  1824.          if(dma_tx_function!=NULL)
  1825.             buffer=dma_tx_function(request->ios2_Data);
  1826.          else
  1827.             buffer=NULL;
  1828.  
  1829.          if(buffer==NULL)
  1830.          {
  1831.             buffer=(ULONG *)unit->tx_buffer;
  1832.             if(!opener->tx_function(buffer,request->ios2_Data,data_size))
  1833.             {
  1834.                error=S2ERR_NO_RESOURCES;
  1835.                wire_error=S2WERR_BUFF_ERROR;
  1836.                ReportEvents(unit,
  1837.                   S2EVENT_ERROR|S2EVENT_SOFTWARE|S2EVENT_BUFF|S2EVENT_TX,
  1838.                   base);
  1839.             }
  1840.          }
  1841.  
  1842.          /* Write packet data */
  1843.  
  1844.          if(error==0)
  1845.          {
  1846.             end=buffer+(send_size>>2);
  1847.             while(buffer<end)
  1848.                LongOut(io_base+EL3REG_DATA0,*buffer++);
  1849.  
  1850.             if((send_size&0x3)!=0)
  1851.                WordOut(io_base+EL3REG_DATA0,*((UWORD *)buffer));
  1852.          }
  1853.  
  1854.          /* Reply packet */
  1855.  
  1856.          request->ios2_Req.io_Error=error;
  1857.          request->ios2_WireError=wire_error;
  1858.          Remove((APTR)request);
  1859.          ReplyMsg((APTR)request);
  1860.  
  1861.          /* Update statistics */
  1862.  
  1863.          if(error==0)
  1864.          {
  1865.             unit->stats.PacketsSent++;
  1866.  
  1867.             tracker=FindTypeStats(unit,&unit->type_trackers,
  1868.                request->ios2_PacketType,base);
  1869.             if(tracker!=NULL)
  1870.             {
  1871.                tracker->stats.PacketsSent++;
  1872.                tracker->stats.BytesSent+=packet_size;
  1873.             }
  1874.          }
  1875.       }
  1876.       else
  1877.          proceed=FALSE;
  1878.    }
  1879.  
  1880.    if(proceed)
  1881.       unit->request_ports[WRITE_QUEUE]->mp_Flags=PA_SOFTINT;
  1882.    else
  1883.    {
  1884.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_SETTXTHRESH
  1885.          |(PREAMBLE_SIZE+packet_size));
  1886.       unit->request_ports[WRITE_QUEUE]->mp_Flags=PA_IGNORE;
  1887.    }
  1888.  
  1889.    return;
  1890. }
  1891.  
  1892.  
  1893.  
  1894. /****i* 3c589.device/TxError ***********************************************
  1895. *
  1896. *   NAME
  1897. *    TxError -- .
  1898. *
  1899. *   SYNOPSIS
  1900. *    TxError(unit)
  1901. *
  1902. *    VOID TxError(struct DevUnit *);
  1903. *
  1904. *   FUNCTION
  1905. *
  1906. *   INPUTS
  1907. *    unit - A unit of this device.
  1908. *
  1909. *   RESULT
  1910. *    None.
  1911. *
  1912. *   EXAMPLE
  1913. *
  1914. *   NOTES
  1915. *
  1916. *   BUGS
  1917. *
  1918. *   SEE ALSO
  1919. *
  1920. ****************************************************************************
  1921. *
  1922. */
  1923.  
  1924. VOID TxError(struct DevUnit *unit,struct DevBase *base)
  1925. {
  1926.    volatile UBYTE *io_base;
  1927.    UBYTE tx_status,flags;
  1928.  
  1929.    base=unit->device;
  1930.    io_base=unit->io_base;
  1931.  
  1932.    /* Gather all errors */
  1933.  
  1934.    while(((tx_status=ByteIn(io_base+EL3REG_TXSTATUS))
  1935.       &EL3REG_TXSTATUSF_COMPLETE)!=0)
  1936.    {
  1937.       flags|=tx_status;
  1938.       ByteOut(io_base+EL3REG_TXSTATUS,0);
  1939.    }
  1940.  
  1941.    /* Restart transmitter if necessary */
  1942.  
  1943.    if((flags&EL3REG_TXSTATUSF_JABBER)!=0)
  1944.    {
  1945.       Disable();
  1946.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_TXRESET);
  1947.       while((LEWordIn(io_base+EL3REG_STATUS)&
  1948.          EL3REG_STATUSF_CMDINPROGRESS)!=0);
  1949.       Enable();
  1950.    }
  1951.  
  1952.    if((flags&(EL3REG_TXSTATUSF_JABBER|EL3REG_TXSTATUSF_OVERFLOW))!=0)
  1953.       LEWordOut(io_base+EL3REG_COMMAND,EL3CMD_TXENABLE);
  1954.  
  1955.    /* Report the error(s) */
  1956.  
  1957.    ReportEvents(unit,S2EVENT_ERROR|S2EVENT_HARDWARE|S2EVENT_TX,base);
  1958.  
  1959.    return;
  1960. }
  1961.  
  1962.  
  1963.  
  1964. /****i* 3c589.device/ReportEvents ******************************************
  1965. *
  1966. *   NAME
  1967. *    ReportEvents -- .
  1968. *
  1969. *   SYNOPSIS
  1970. *    ReportEvents(unit,events)
  1971. *
  1972. *    VOID ReportEvents(struct DevUnit *,ULONG);
  1973. *
  1974. *   FUNCTION
  1975. *
  1976. *   INPUTS
  1977. *    unit - A unit of this device.
  1978. *    events - A mask of events to report.
  1979. *
  1980. *   RESULT
  1981. *    None.
  1982. *
  1983. *   EXAMPLE
  1984. *
  1985. *   NOTES
  1986. *
  1987. *   BUGS
  1988. *
  1989. *   SEE ALSO
  1990. *
  1991. ****************************************************************************
  1992. *
  1993. */
  1994.  
  1995. static VOID ReportEvents(struct DevUnit *unit,ULONG events,
  1996.    struct DevBase *base)
  1997. {
  1998.    struct IOSana2Req *request,*tail,*next_request;
  1999.    struct List *list;
  2000.  
  2001.    list=&unit->request_ports[EVENT_QUEUE]->mp_MsgList;
  2002.    next_request=(APTR)list->lh_Head;
  2003.    tail=(APTR)&list->lh_Tail;
  2004.  
  2005.    Disable();
  2006.    while(next_request!=tail)
  2007.    {
  2008.       request=next_request;
  2009.       next_request=(APTR)request->ios2_Req.io_Message.mn_Node.ln_Succ;
  2010.  
  2011.       if((request->ios2_WireError&events)!=0)
  2012.       {
  2013.          request->ios2_WireError=events;
  2014.          Remove((APTR)request);
  2015.          ReplyMsg((APTR)request);
  2016.       }
  2017.    }
  2018.    Enable();
  2019.  
  2020.    return;
  2021. }
  2022.  
  2023.  
  2024.  
  2025. /****i* 3c589.device/UnitTask **********************************************
  2026. *
  2027. *   NAME
  2028. *    UnitTask -- .
  2029. *
  2030. *   SYNOPSIS
  2031. *    UnitTask()
  2032. *
  2033. *    VOID UnitTask();
  2034. *
  2035. *   FUNCTION
  2036. *
  2037. *   INPUTS
  2038. *
  2039. *   RESULT
  2040. *
  2041. *   EXAMPLE
  2042. *
  2043. *   NOTES
  2044. *
  2045. *   BUGS
  2046. *
  2047. *   SEE ALSO
  2048. *
  2049. ****************************************************************************
  2050. *
  2051. */
  2052.  
  2053. static VOID UnitTask()
  2054. {
  2055.    struct Task *task;
  2056.    struct IORequest *request;
  2057.    struct DevUnit *unit;
  2058.    struct DevBase *base;
  2059.    struct MsgPort *general_port;
  2060.    ULONG signals,wait_signals,card_removed_signal,card_inserted_signal,
  2061.       general_port_signal;
  2062.  
  2063.    /* Get parameters */
  2064.  
  2065.    task=AbsExecBase->ThisTask;
  2066.    unit=task->tc_UserData;
  2067.    base=unit->device;
  2068.  
  2069.    /* Activate general request port */
  2070.  
  2071.    general_port=unit->request_ports[GENERAL_QUEUE];
  2072.    general_port->mp_SigTask=task;
  2073.    general_port->mp_SigBit=AllocSignal(-1);
  2074.    general_port_signal=1<<general_port->mp_SigBit;
  2075.    general_port->mp_Flags=PA_SIGNAL;
  2076.  
  2077.    /* Allocate a signal for notification of card removal */
  2078.  
  2079.    card_removed_signal=unit->card_removed_signal=1<<AllocSignal(-1);
  2080.    card_inserted_signal=unit->card_inserted_signal=1<<AllocSignal(-1);
  2081.    wait_signals=(1<<general_port->mp_SigBit)|card_removed_signal
  2082.       |card_inserted_signal;
  2083.  
  2084.    /* Tell ourselves to check port for old messages */
  2085.  
  2086.    Signal(task,general_port_signal);
  2087.  
  2088.    /* Infinite loop to service requests and signals */
  2089.  
  2090.    while(TRUE)
  2091.    {
  2092.       signals=Wait(wait_signals);
  2093.  
  2094.       if((signals&card_inserted_signal)!=0)
  2095.       {
  2096.          if(InitialiseCard(unit,base))
  2097.          {
  2098.             unit->flags|=UNITF_HAVECARD;
  2099.             if((unit->flags&UNITF_CONFIGURED)!=0)
  2100.                ConfigureAdapter(unit,base);
  2101.          }
  2102.          else
  2103.             ReleaseCard(unit->card_handle,0);
  2104.       }
  2105.  
  2106.       if((signals&card_removed_signal)!=0)
  2107.       {
  2108.          ReleaseCard(unit->card_handle,0);
  2109.          GoOffline(unit,base);
  2110.       }
  2111.  
  2112.       if((signals&general_port_signal)!=0)
  2113.       {
  2114.          while((request=(APTR)GetMsg(general_port))!=NULL)
  2115.          {
  2116.             /* Service the request as soon as the unit is free */
  2117.  
  2118.             ObtainSemaphore(&unit->access_lock);
  2119.             ServiceRequest((APTR)request,base);
  2120.          }
  2121.       }
  2122.    }
  2123. }
  2124.  
  2125.  
  2126.  
  2127. /****i* 3c589.device/ReadEEPROM ********************************************
  2128. *
  2129. *   NAME
  2130. *    ReadEEPROM -- .
  2131. *
  2132. *   SYNOPSIS
  2133. *    value = ReadEEPROM(io_base,index)
  2134. *
  2135. *    UWORD ReadEEPROM(UBYTE *,UWORD);
  2136. *
  2137. *   FUNCTION
  2138. *
  2139. *   INPUTS
  2140. *    io_base - Base of adapter's register window.
  2141. *    index - Offset within EEPROM.
  2142. *
  2143. *   RESULT
  2144. *    value - Contents of specified EEPROM location.
  2145. *
  2146. *   EXAMPLE
  2147. *
  2148. *   NOTES
  2149. *
  2150. *   BUGS
  2151. *
  2152. *   SEE ALSO
  2153. *
  2154. ****************************************************************************
  2155. *
  2156. */
  2157.  
  2158. static UWORD ReadEEPROM(volatile UBYTE *io_base,UWORD index)
  2159. {
  2160.    LEWordOut(io_base+EL3REG_EEPROMCMD,EL3ECMD_READ|index);
  2161.    while((LEWordIn(io_base+EL3REG_EEPROMCMD)&EL3REG_EEPROMCMDF_BUSY)
  2162.       !=0);
  2163.    return LEWordIn(io_base+EL3REG_EEPROMDATA);
  2164. }
  2165.  
  2166.  
  2167.  
  2168. static UWORD LEWordIn(volatile UBYTE *address)
  2169. {
  2170.    UWORD datum;
  2171.  
  2172.    datum=*((volatile UWORD *)(address));
  2173.    return (datum<<8)|(datum>>8);
  2174. }
  2175.  
  2176.  
  2177.  
  2178.